using MicroMsg.Common.Audio.Amr;
using MicroMsg.Common.Utils;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using System;
using System.Windows.Threading;
namespace MicroMsg.Scene.Voice
{
	public class RecorderVoice
	{
		private const string TAG = "RecorderVoice";
		private const int STATUS_INIT = 0;
		private const int STATUS_START = 1;
		private const int STATUS_STOP = 2;
		public static IRecorderContext mRecorderContext = null;
		private static double mStartTimestamp = 0.0;
		private static int mStatus = 0;
		private static byte[] mOutputVoiceBuffer = new byte[65536];
		private static int mOutputVoiceLength = 0;
		private static int mOutputTimeLength = 0;
		private static Microphone mMicroPhone = null;
		private static AMREncodeFloat mAmrEncoder = new AMREncodeFloat();
		private static DispatcherTimer mDispatcherTimer = null;
		private static byte[] mSampleOutputBuffer = null;
		private static bool mDeviceOpened = false;
		public static bool start(IRecorderContext recorderContext, object args)
		{
			if (RecorderVoice.mStatus == 1)
			{
				Log.smethod_1("RecorderVoice", "recorder runing already.");
				return false;
			}
			RecorderVoice.mStatus = 1;
			RecorderVoice.mStartTimestamp = Util.getNowMilliseconds();
			RecorderVoice.mRecorderContext = recorderContext;
			RecorderVoice.mRecorderContext.onStartup((int)(RecorderVoice.mStartTimestamp / 1000.0), args);
			RecorderVoice.mOutputVoiceLength = 0;
			RecorderVoice.openMicroPhoneDevice();
			ServiceCenter.perfReportMgr.appendPerfItem(1u, (uint)(Util.getNowMilliseconds() - RecorderVoice.mStartTimestamp));
			return true;
		}
		public static bool isRunning()
		{
			return RecorderVoice.mStatus == 1 || RecorderVoice.mDeviceOpened;
		}
		public static bool stop()
		{
			if (RecorderVoice.mStatus != 1)
			{
				Log.smethod_1("RecorderVoice", "recorder stop with not start.");
				return false;
			}
			Log.smethod_5("RecorderVoice", "recorder stop.");
			double nowMilliseconds = Util.getNowMilliseconds();
			RecorderVoice.mStatus = 2;
			RecorderVoice.mOutputTimeLength = RecorderVoice.getVoiceTime();
			if (RecorderVoice.mRecorderContext != null)
			{
				RecorderVoice.mRecorderContext.onVoiceTimeChanged(RecorderVoice.mOutputTimeLength);
			}
			if (RecorderVoice.processSampleBuffer() == RecorderVoice.mSampleOutputBuffer.Length)
			{
				RecorderVoice.processSampleBuffer();
			}
			RecorderVoice.doStop();
			ServiceCenter.perfReportMgr.appendPerfItem(3u, (uint)(Util.getNowMilliseconds() - nowMilliseconds));
			return true;
		}
		public static void checkDeviceStop()
		{
			if (RecorderVoice.mStatus == 2 && RecorderVoice.mDeviceOpened)
			{
				RecorderVoice.doStop();
			}
		}
		private static int getVoiceTime()
		{
			int num = (int)(Util.getNowMilliseconds() - RecorderVoice.mStartTimestamp);
			if (num >= 2500)
			{
				num -= 1499;
			}
			else
			{
				if (num > 1000)
				{
					num = 1001;
				}
			}
			return num;
		}
		private static void doStop()
		{
			RecorderVoice.closeMicroPhoneDevice();
			if (RecorderVoice.mRecorderContext != null)
			{
				RecorderVoice.mRecorderContext.onStop(RecorderVoice.mOutputVoiceBuffer, RecorderVoice.mOutputVoiceLength, RecorderVoice.mOutputTimeLength);
			}
			RecorderVoice.mRecorderContext = null;
		}
		private static void openMicroPhoneDevice()
		{
			try
			{
				if (RecorderVoice.mDeviceOpened)
				{
					Log.smethod_1("RecorderVoice", "openMicroPhoneDevice error.  not been closed. ");
				}
				else
				{
					RecorderVoice.mDeviceOpened = true;
					if (RecorderVoice.mMicroPhone == null)
					{
						RecorderVoice.mMicroPhone = Microphone.get_Default();
						RecorderVoice.mMicroPhone.add_BufferReady(new EventHandler<EventArgs>(RecorderVoice.onMicroPhoneBufferReady));
						RecorderVoice.mMicroPhone.set_BufferDuration(TimeSpan.FromMilliseconds(1000.0));
						RecorderVoice.mSampleOutputBuffer = new byte[RecorderVoice.mMicroPhone.GetSampleSizeInBytes(RecorderVoice.mMicroPhone.get_BufferDuration())];
					}
					RecorderVoice.mDispatcherTimer = new DispatcherTimer();
					RecorderVoice.mDispatcherTimer.set_Interval(TimeSpan.FromMilliseconds(300.0));
					RecorderVoice.mDispatcherTimer.add_Tick(new EventHandler(RecorderVoice.onXnaDispatcherTimer));
					RecorderVoice.mDispatcherTimer.Start();
					FrameworkDispatcher.Update();
					RecorderVoice.mMicroPhone.Start();
					Log.smethod_5("RecorderVoice", "microphone record start ...");
				}
			}
			catch (Exception ex)
			{
				Log.smethod_1("RecorderVoice", "openMicroPhoneDevice error. e= " + ex.ToString());
			}
		}
		private static void onXnaDispatcherTimer(object sender, EventArgs e)
		{
			try
			{
				FrameworkDispatcher.Update();
			}
			catch (Exception ex)
			{
				Log.smethod_1("RecorderVoice", "onXnaDispatcherTimer error. e= " + ex.get_Message());
			}
		}
		public static void checkFrameworkUpdate()
		{
			if (RecorderVoice.mStatus == 1 && RecorderVoice.mDeviceOpened)
			{
				RecorderVoice.onXnaDispatcherTimer(null, null);
			}
		}
		private static void onMicroPhoneBufferReady(object sender, EventArgs e)
		{
			if (!RecorderVoice.mDeviceOpened)
			{
				return;
			}
			RecorderVoice.processSampleBuffer();
		}
		private static void updateVoiceTime()
		{
			if (RecorderVoice.mRecorderContext != null && RecorderVoice.mStatus == 1)
			{
				RecorderVoice.mRecorderContext.onVoiceTimeChanged(RecorderVoice.getVoiceTime());
			}
		}
		private static int processSampleBuffer()
		{
			if (RecorderVoice.mMicroPhone.get_State() != null)
			{
				Log.smethod_1("RecorderVoice", "onMicroPhoneBufferReady, status error.");
				return 0;
			}
			int data = RecorderVoice.mMicroPhone.GetData(RecorderVoice.mSampleOutputBuffer);
			if (data <= 0 || data > RecorderVoice.mSampleOutputBuffer.Length)
			{
				Log.smethod_1("RecorderVoice", "no data ready,count = " + data);
				return 0;
			}
			if (RecorderVoice.mRecorderContext != null && RecorderVoice.mRecorderContext.isNeedData())
			{
				RecorderVoice.updateVoiceTime();
				RecorderVoice.encodeAmrFromBuffer(RecorderVoice.mRecorderContext, RecorderVoice.mSampleOutputBuffer, data);
				return data;
			}
			Log.smethod_1("RecorderVoice", "context is finished.");
			return 0;
		}
		private static void encodeAmrFromBuffer(IRecorderContext context, byte[] pcmbuffer, int count)
		{
			int num = 0;
			int num2 = count / 640;
			byte[] array = new byte[2600];
			for (int i = 0; i < num2; i++)
			{
				int num3 = 0;
				RecorderVoice.mAmrEncoder.pcm16K2AmrFast(pcmbuffer, i * 640, array, ref num3);
				num += num3;
				if (num3 > 0)
				{
					context.onAppendOutputData(array, 0, num3);
					if (RecorderVoice.mOutputVoiceLength + num3 < RecorderVoice.mOutputVoiceBuffer.Length)
					{
						Buffer.BlockCopy(array, 0, RecorderVoice.mOutputVoiceBuffer, RecorderVoice.mOutputVoiceLength, num3);
						RecorderVoice.mOutputVoiceLength += num3;
					}
				}
			}
		}
		private static void closeMicroPhoneDevice()
		{
			try
			{
				if (!RecorderVoice.mDeviceOpened)
				{
					Log.smethod_1("RecorderVoice", "closeMicroPhoneDevice error, status error.");
				}
				else
				{
					RecorderVoice.mDeviceOpened = false;
					if (RecorderVoice.mMicroPhone != null && RecorderVoice.mMicroPhone.get_State() == null)
					{
						RecorderVoice.mMicroPhone.Stop();
					}
					if (RecorderVoice.mDispatcherTimer != null)
					{
						RecorderVoice.mDispatcherTimer.Stop();
						RecorderVoice.mDispatcherTimer = null;
					}
				}
			}
			catch (Exception ex)
			{
				Log.smethod_1("RecorderVoice", "closeMicroPhoneDevice error. e= " + ex.ToString());
			}
		}
	}
}
